Kotlin Vocabulary | Collection 和 Sequence
腾讯视频链接 https://v.qq.com/x/page/d09360fuh1s.html Bilibili 视频链接 https://www.bilibili.com/video/av97781019/
Collection 和 Sequence 的对比
Collection (也称集合) 是在每次操作时立即执行的,执行结果会存储到一个新的集合中。作用于 Collection 的转换操作是内联函数。例如,map 的实现方式,可以看到它是一个创建了新 ArrayList 的内联函数:
public inline fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R> {
return mapTo(ArrayList<R>(collectionSizeOrDefault(10)), transform)
}
内联函数
https://kotlinlang.org/docs/reference/inline-functions.html
map
https://github.com/JetBrains/kotlin/blob/master/libraries/stdlib/common/src/generated/_Collections.kt#L1312
public fun <T, R> Sequence<T>.map(transform: (T) -> R): Sequence<R>{
return TransformingSequence(this, transform)
}
map
https://github.com/JetBrains/kotlin/blob/master/libraries/stdlib/common/src/generated/_Sequences.kt#L860
例如 first 这样的末端操作,会对 Sequence 中的元素进行遍历,直到预置条件匹配为止。
public inline fun <T> Sequence<T>.first(predicate: (T) -> Boolean): T {
for (element in this) if (predicate(element)) return element
throw NoSuchElementException(“Sequence contains no element matching the predicate.”)
}
first
https://github.com/JetBrains/kotlin/blob/master/libraries/stdlib/common/src/generated/_Sequences.kt#L117
如果观察 TransformingSequence 这样的类型是如何实现的,我们会发现在迭代器上调用 next 时,转换存储操作也一并被应用。
internal class TransformingIndexedSequence<T, R>
constructor(private val sequence: Sequence<T>, private val transformer: (Int, T) -> R) : Sequence<R> {
override fun iterator(): Iterator<R> = object : Iterator<R> {
…
override fun next(): R {
return transformer(checkIndexOverflow(index++), iterator.next())
}
…
}
了解这些操作 https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/#functions
Collection 和 Sequence 如何选择
Collections
调用 map 时 —— 一个新的 ArrayList 会被创建。我们遍历了初始 Collection 中所有项目,复制原始的对象,然后更改它的颜色,再将其添加到新的列表中;
调用 first 时 —— 遍历每一个项目,直到找到第一个正方形。
asSequence —— 基于原始集合的迭代器创建一个 Sequence;
调用 map 时 —— Sequence 会将转换操作的信息存储到一个列表中,该列表只会存储要执行的操作,并不会执行这些操作;
调用 first 时 —— 这是一个末端操作,所以会将中间操作作用到集合中的每个元素。我们遍历初始集合,对每个元素执行 map 操作,然后继续执行 first 操作,当遍历到第二个元素时,发现它符合我们的要求,所以就无需在剩余的元素中进行 map 操作了。
性能
转换的顺序
因为末端操作可以提前对任务进行处理,而中间操作会延迟进行处理,所以在某些情况下,相比于 Collection,Sequence 可以避免一些无用操作。使用时,请确保检查了转换顺序以及它们的依赖关系。
Collection 的操作使用了内联函数,所以处理所用到的字节码以及传递给它的 lambda 字节码都会进行内联操作。而 Sequence 不使用内联函数,因此,它会为每个操作创建新的 Function 对象。
想了解更多 Android 内容?
在公众号首页发送关键词 "Android",获取相关历史技术文章;
在公众号首页发送关键词 "ADS",获取开发者峰会演讲中文字幕视频;
还有更多疑惑?欢迎点击菜单 "联系我们" 反馈您在开发过程中遇到的问题。
推荐阅读